#include "StdAfx.h"
#include "cfdGrid.h"


//two parameter constructor
cfdGrid::cfdGrid(int x,int y){this->x=x;
this->y=y;
body=new double*[x];   for(int i=0;i<x;i++)    body[i]=new double[y];
for(int i=0;i<x;i++)
	memset(body[i],0,sizeof(double)*(y));
}

//copy constructor
cfdGrid::cfdGrid( const cfdGrid &o ) : x(o.x ), y(o.y) 
{
	body=new double*[x];   for(int i=0;i<x;i++)    body[i]=new double[y];
	for(int i=0;i<x;i++)
		memcpy(body[i],o.body[i],sizeof(double)*(y));
}

//assignment operator overload
cfdGrid& cfdGrid::operator=(const cfdGrid &o)
{
	x=o.x; y=o.y;
	body=new double*[x];   for(int i=0;i<x;i++)    body[i]=new double[y];
	for(int i=0;i<x;i++)
		memcpy(body[i],o.body[i],sizeof(double)*(y));
	return *this;
}

//Tridiagonal Solve of a nx X 3 cfdGrid
void cfdGrid::TridiagonalSolve(){
int i;
    for(i = 1; i < x; i++){
        body[i][0] = body[i][0]/body[i-1][1];
        body[i][1] = body[i][1] - body[i][0]*body[i-1][2];
		body[i][3] = body[i][3] - body[i][0]*body[i-1][3];
    }
 
    body[x-1][3] = body[x-1][3]/body[x-1][1];
 
    for (i = x - 2; i >= 0; i--)
        body[i][3]=(body[i][3]-body[i][2]*body[i+1][3])/body[i][1];
}

//Gauss-Elimination Solution WITHOUT partial pivot
void cfdGrid::GElimSolve(){
	int i,j,k;	//counters for loops
	int n=x;	//no. of unknowns
	for(i=0;i<n-1;i++)	//n-1 iterations from 1st to second last column
	{
			for(j=i+1;j<n;j++) // beginning from one down row to last row
			{
				body[j][i]=(body[j][i]/body[i][i]);
				for(k=i+1;k<=n;k++)		//beginning from diagonal entry to last entry of aug. matrix
					body[j][k]=body[j][k]-body[j][i]*body[i][k];
			}
	}
	body[n-1][n]=body[n-1][n]/body[n-1][n-1];
	for(j=n-2;j>=0;j--)	//from second last row to top
	{
		for(k=j+1;k<=n-1;k++)	//from element next to diagonal to last coefficient
			body[j][n]=body[j][n]-body[j][k]*body[k][n];
		body[j][n]=(body[j][n]/body[j][j]);
	}  
}

//takes a pointer to an array(sequential) as destination to copy the grid data 
void cfdGrid::toArray(double*ar){
	for(int i=0;i<x;i++){
		memcpy_s(ar,sizeof(double)*(y),body[i],sizeof(double)*(y));
				ar+=x;
	}
}

//takes a pointer to a two-d array(array of pointers to 1-d array) as destination to copy the grid data 
void cfdGrid::toArray(double**ar){
	for(int i=0;i<x;i++){
		memcpy_s(ar[i],sizeof(double)*(y),body[i],sizeof(double)*(y));
	}
}

//takes a pointer to a two-d array(sequential) as source to copy to grid
void cfdGrid::toGrid(double*ar){
	for(int i=0;i<x;i++){
		memcpy_s(body[i],sizeof(double)*(y),ar,sizeof(double)*(y));
				ar+=x;
	}
}

//takes a pointer to a two-d array(array of pointers to array of doubles) as source to copy to grid data 
void cfdGrid::toGrid(double**ar){
	for(int i=0;i<x;i++){
		memcpy_s(body[i],sizeof(double)*(y),ar[i],sizeof(double)*(y));
	}
}

//calculates fxy and stores its value for each point in grid
void cfdGrid::fillGrid(char* fxy,double dx,double dy){
	double X,Y,cert;
	RVar xvar ( "x" , &X );
	RVar yvar ( "y" , &Y );
	RVar* vararray[2];
	vararray[0]=&xvar; vararray[1]=&yvar;
	ROperation op ( fxy, 2, vararray );
	for(int i=0;i<x;i++)
		for(int j=0;j<y;j++)
		{
			X=dx*i;
			Y=dy*j;
			cert=op.Val();
			body[i][j]=op.Val();
		}
}

//calculates and stores boundary values depending on bound expression array(index going clockwise, 0 for left)
void cfdGrid::fillBoundary(char bound[4][128],double dx,double dy){
	double X;
	RVar xvar ( "x" , &X );
	RVar* vararray[1]; 
	vararray[0]=&xvar;
	for(int k=0;k<4;k++){
		ROperation op ( bound[k], 1, vararray );
		int m=k%2?y-1:x-1;
		if(k==0||k==3)	m=0;
		if(k%2)
			for(int i=0;i<x;i++)
			{
				X=dx*i;
				body[i][m]=op.Val();
			}
		else
			for(int j=0;j<y;j++)
			{
				X=dy*j;
				body[m][j]=op.Val();
			}
	}
}